/*
 * Author: Hiawui
 * Date: 2010/12/06
 ******************************************************************************
 * Memory Pool
 * This is a replacement of malloc, calloc and free
 *
 */

#ifndef __HV_MEM_POOL_H__
#define __HV_MEM_POOL_H__

typedef unsigned int     hv_msize_t;    /* type of memory size */

#define MAX_INDEX   30
#define MB_MAGIC0   0xBCB00CBC
#define MB_MAGIC1   0xA00DADAD

/*
 * Memory pool error codes
 */
#define HV_MP_ERR_NONE      0   /* No error */
#define HV_MP_ERR_ALLOC     1   /* No memory available */
#define HV_MP_ERR_ARG_NULL  2   /* function argument is null */
#define HV_MP_ERR_TOO_BIG   3   /* exceeded max size */
#define HV_MP_ERR_OVERWRITE 4   /* the block is overwriten */
#define HV_MP_ERR_BLOCK     5   /* block indicator error */
#define HV_MP_ERR_FREED     6   /* the block is freed */

/*
 * Node of memory block
 */
typedef struct hv_mp_block_t
{
    unsigned int                mb_magic0;  /* lower bound magic */
    unsigned int                mb_flag;     /* block flag */
    hv_msize_t                  mb_size;    /* the size of the free memory in this block */
    struct hv_mp_block_t*       mb_next;    /* pointer to next block */
    unsigned int                mb_magic1;  /* upper bound magic */
}hv_mp_block_t;

/*
 * Node of free block
 */
typedef struct hv_free_block_t
{
    struct hv_free_block_t*     fb_next;    /* pointer to next block */
}hv_free_block_t;

/*
 * memory pool handle
 */
typedef struct hv_mpool_t
{
    hv_msize_t                  mp_pagesize;   /* Internal page size */
    hv_mp_block_t*              mp_head;   /* The header of the memory block list */
    hv_free_block_t*            mp_free_list[MAX_INDEX+1];  /* The free block list basic on index */
}hv_mpool_t;


/*
 * Create new memory pool
 * errno_p: error code
 */
hv_mpool_t* hv_mpool_create(int* errno_p);

/*
 * Allocate memory from pool
 * mp_p: memory pool
 * size: the size to be allocated
 * errno_p: error code
 */
void* hv_mpool_alloc(hv_mpool_t* mp_p, hv_msize_t size, int* errno_p);

/*
 * Allocate memory from pool, initialize memory to 0
 * mp_p: memory pool
 * size: size to be allocated
 * errno_p: error code
 */
void* hv_mpool_calloc(hv_mpool_t* mp_p, hv_msize_t size, int* errno_p);

/*
 * Resize the allocated memory, content is not changed by either new_size,
 * or old size lenght, whichever the less
 * mp_p: pointer to memory pool
 * addr: memory address
 * new_size: new size of the memory
 * errno_p: error code
 */
void* hv_mpool_realloc(hv_mpool_t* mp_p, void* addr, hv_msize_t new_size, int* errno_p);

/*
 * Free the addr to pool
 * mp_p: pointer to memory pool
 * addr: address to be freed
 * errno_p: error code
 */
void hv_mpool_free(hv_mpool_t* mp_p, void* addr, int* errno_p);

/*
 * Release all memory to OS, destroy the memory pool
 * mp_p: pointer to memory pool
 * errno_p: error code
 */
void hv_mpool_destroy(hv_mpool_t* mp_p, int* errno_p);

/*
 * Return error message of error code
 * errno: the error code
 */
const char* hv_mpool_strerr(const int e);

#endif
